﻿Imports System
Imports System.CodeDom
Imports System.Collections
Imports System.Globalization
Imports System.Reflection

Namespace System.Workflow.ComponentModel.Compiler
    Friend NotInheritable Class DesignTimePropertyInfo
        Inherits PropertyInfo
        ' Methods
        Friend Sub New(ByVal declaringType As DesignTimeType, ByVal [property] As CodeMemberProperty)
            Me.property = [property]
            Me.declaringType = declaringType
        End Sub

        Public Overrides Function GetAccessors(ByVal nonPublic As Boolean) As MethodInfo()
            Dim list As New ArrayList
            If Helper.IncludeAccessor(Me.GetGetMethod(nonPublic), nonPublic) Then
                list.Add(Me.getMethod)
            End If
            If Helper.IncludeAccessor(Me.GetSetMethod(nonPublic), nonPublic) Then
                list.Add(Me.setMethod)
            End If
            Return [TryCast](list.ToArray(GetType(MethodInfo)),MethodInfo())
        End Function

        Public Overrides Function GetCustomAttributes(ByVal inherit As Boolean) As Object()
            Return Me.GetCustomAttributes(GetType(Object), inherit)
        End Function

        Public Overrides Function GetCustomAttributes(ByVal attributeType As Type, ByVal inherit As Boolean) As Object()
            If (attributeType Is Nothing) Then
                Throw New ArgumentNullException("attributeType")
            End If
            If (Me.attributes Is Nothing) Then
                Me.attributes = Helper.LoadCustomAttributes(Me.property.CustomAttributes, [TryCast](Me.DeclaringType,DesignTimeType))
            End If
            Return Helper.GetCustomAttributes(attributeType, inherit, Me.attributes, Me)
        End Function

        Public Overrides Function GetGetMethod(ByVal nonPublic As Boolean) As MethodInfo
            If (Me.CanRead AndAlso (Me.getMethod Is Nothing)) Then
                Dim name As String = ("get_" & Me.Name)
                Me.getMethod = New PropertyMethodInfo(True, name, Me)
            End If
            If (Not nonPublic AndAlso ((Me.getMethod Is Nothing) OrElse ((Me.getMethod.Attributes And MethodAttributes.Public) <> MethodAttributes.Public))) Then
                Return Nothing
            End If
            Return Me.getMethod
        End Function

        Public Overrides Function GetIndexParameters() As ParameterInfo()
            Dim length As Integer = 0
            Dim parameters As ParameterInfo() = Nothing
            Dim getMethod As MethodInfo = Me.GetGetMethod(True)
            If (Not getMethod Is Nothing) Then
                parameters = getMethod.GetParameters
                length = parameters.Length
            Else
                getMethod = Me.GetSetMethod(True)
                If (Not getMethod Is Nothing) Then
                    parameters = getMethod.GetParameters
                    length = (parameters.Length - 1)
                End If
            End If
            Dim infoArray2 As ParameterInfo() = New ParameterInfo(length  - 1) {}
            Dim i As Integer
            For i = 0 To length - 1
                infoArray2(i) = parameters(i)
            Next i
            Return infoArray2
        End Function

        Public Overrides Function GetSetMethod(ByVal nonPublic As Boolean) As MethodInfo
            If (Me.CanWrite AndAlso (Me.setMethod Is Nothing)) Then
                Dim name As String = ("set_" & Me.Name)
                Me.setMethod = New PropertyMethodInfo(False, name, Me)
            End If
            If (Not nonPublic AndAlso ((Me.setMethod Is Nothing) OrElse ((Me.setMethod.Attributes And MethodAttributes.Public) <> MethodAttributes.Public))) Then
                Return Nothing
            End If
            Return Me.setMethod
        End Function

        Public Overrides Function GetValue(ByVal obj As Object, ByVal invokeAttr As BindingFlags, ByVal binder As Binder, ByVal index As Object(), ByVal culture As CultureInfo) As Object
            Throw New NotImplementedException(TypeSystemSR.GetString("Error_RuntimeNotSupported"))
        End Function

        Public Overrides Function IsDefined(ByVal attributeType As Type, ByVal inherit As Boolean) As Boolean
            If (attributeType Is Nothing) Then
                Throw New ArgumentNullException("attributeType")
            End If
            If (Me.attributes Is Nothing) Then
                Me.attributes = Helper.LoadCustomAttributes(Me.property.CustomAttributes, [TryCast](Me.DeclaringType,DesignTimeType))
            End If
            Return Helper.IsDefined(attributeType, inherit, Me.attributes, Me)
        End Function

        Public Overrides Sub SetValue(ByVal obj As Object, ByVal value As Object, ByVal invokeAttr As BindingFlags, ByVal binder As Binder, ByVal index As Object(), ByVal culture As CultureInfo)
            Throw New NotImplementedException(TypeSystemSR.GetString("Error_RuntimeNotSupported"))
        End Sub


        ' Properties
        Public Overrides ReadOnly Property Attributes As PropertyAttributes
            Get
                Return PropertyAttributes.None
            End Get
        End Property

        Public Overrides ReadOnly Property CanRead As Boolean
            Get
                Return Me.property.HasGet
            End Get
        End Property

        Public Overrides ReadOnly Property CanWrite As Boolean
            Get
                Return Me.property.HasSet
            End Get
        End Property

        Friend ReadOnly Property CodeMemberProperty As CodeMemberProperty
            Get
                Return Me.property
            End Get
        End Property

        Public Overrides ReadOnly Property DeclaringType As Type
            Get
                Return Me.declaringType
            End Get
        End Property

        Public Overrides ReadOnly Property Name As String
            Get
                Return Helper.EnsureTypeName(Me.property.Name)
            End Get
        End Property

        Public Overrides ReadOnly Property PropertyType As Type
            Get
                Return Me.declaringType.ResolveType(DesignTimeType.GetTypeNameFromCodeTypeReference(Me.property.Type, Me.declaringType))
            End Get
        End Property

        Public Overrides ReadOnly Property ReflectedType As Type
            Get
                Return Me.declaringType
            End Get
        End Property


        ' Fields
        Private attributes As Attribute()
        Private declaringType As DesignTimeType
        Private getMethod As MethodInfo
        Private [property] As CodeMemberProperty
        Private setMethod As MethodInfo

        ' Nested Types
        Private NotInheritable Class PropertyMethodInfo
            Inherits MethodInfo
            ' Methods
            Friend Sub New(ByVal isGetter As Boolean, ByVal name As String, ByVal [property] As DesignTimePropertyInfo)
                Me.isGetter = isGetter
                Me.name = name
                Me.property = [property]
            End Sub

            Public Overrides Function GetBaseDefinition() As MethodInfo
                Throw New NotImplementedException
            End Function

            Public Overrides Function GetCustomAttributes(ByVal inherit As Boolean) As Object()
                Return Me.GetCustomAttributes(GetType(Object), inherit)
            End Function

            Public Overrides Function GetCustomAttributes(ByVal attributeType As Type, ByVal inherit As Boolean) As Object()
                Return New Object(0  - 1) {}
            End Function

            Public Overrides Function GetMethodImplementationFlags() As MethodImplAttributes
                Return MethodImplAttributes.IL
            End Function

            Public Overrides Function GetParameters() As ParameterInfo()
                If (Me.parameters Is Nothing) Then
                    Dim parameters As CodeParameterDeclarationExpressionCollection = Me.property.CodeMemberProperty.Parameters
                    Dim infoArray As ParameterInfo() = New ParameterInfo(If(Me.IsGetter, parameters.Count, (parameters.Count + 1))  - 1) {}
                    Dim i As Integer
                    For i = 0 To parameters.Count - 1
                        infoArray(i) = New DesignTimeParameterInfo(parameters.Item(i), i, Me.property)
                    Next i
                    If Not Me.IsGetter Then
                        Dim codeParameter As New CodeParameterDeclarationExpression(Me.property.CodeMemberProperty.Type.BaseType, "value") { _
                            .Direction = FieldDirection.In _
                        }
                        infoArray(parameters.Count) = New DesignTimeParameterInfo(codeParameter, 0, Me.property)
                    End If
                    Me.parameters = infoArray
                End If
                Return Me.parameters
            End Function

            Public Overrides Function Invoke(ByVal obj As Object, ByVal invokeAttr As BindingFlags, ByVal binder As Binder, ByVal parameters As Object(), ByVal culture As CultureInfo) As Object
                Throw New NotImplementedException(TypeSystemSR.GetString("Error_RuntimeNotSupported"))
            End Function

            Public Overrides Function IsDefined(ByVal attributeType As Type, ByVal inherit As Boolean) As Boolean
                Return False
            End Function


            ' Properties
            Public Overrides ReadOnly Property Attributes As MethodAttributes
                Get
                    Return (Helper.ConvertToMethodAttributes(Me.property.CodeMemberProperty.Attributes) Or MethodAttributes.SpecialName)
                End Get
            End Property

            Public Overrides ReadOnly Property DeclaringType As Type
                Get
                    Return Me.property.declaringType
                End Get
            End Property

            Friend ReadOnly Property IsGetter As Boolean
                Get
                    Return Me.isGetter
                End Get
            End Property

            Public Overrides ReadOnly Property MethodHandle As RuntimeMethodHandle
                Get
                    Throw New NotImplementedException(TypeSystemSR.GetString("Error_RuntimeNotSupported"))
                End Get
            End Property

            Public Overrides ReadOnly Property Name As String
                Get
                    Return Helper.EnsureTypeName(Me.name)
                End Get
            End Property

            Public Overrides ReadOnly Property ReflectedType As Type
                Get
                    Return Me.property.declaringType
                End Get
            End Property

            Public Overrides ReadOnly Property ReturnParameter As ParameterInfo
                Get
                    Throw New NotImplementedException
                End Get
            End Property

            Public Overrides ReadOnly Property ReturnType As Type
                Get
                    If Me.isGetter Then
                        Return DirectCast(Me.DeclaringType, DesignTimeType).ResolveType(DesignTimeType.GetTypeNameFromCodeTypeReference(Me.property.CodeMemberProperty.Type, DirectCast(Me.DeclaringType, DesignTimeType)))
                    End If
                    Return GetType(Void)
                End Get
            End Property

            Public Overrides ReadOnly Property ReturnTypeCustomAttributes As ICustomAttributeProvider
                Get
                    Throw New NotImplementedException
                End Get
            End Property


            ' Fields
            Private isGetter As Boolean
            Private name As String = String.Empty
            Private parameters As ParameterInfo()
            Private [property] As DesignTimePropertyInfo
        End Class
    End Class
End Namespace

